function cb(callback, p0,p1,p2) {
    try{
        if( callback && callback && typeof callback){
            callback(p0,p1,p2);
        }
    }
    catch (e) {
        console.log(e);
    }
};
function extend( a , b) {
    try{
        if( a==null || !a){
            a = {};
        }
        if( b && b!=null){
            for( p in b ){
                a[p] = b[p];
            }
        }
    }
    catch (e) {
        console.log(e);
    }
    return a;
};
function getNewId(header) {
    var me = this;
    var res ="";
    try{
        res =[header , ( new Date()).getTime().toString() , parseInt(1000*(Math.random())).toString()].join('_');
    }
    catch (e) {
        console.log(e);
    }
    return res;
};
function TKmsApp(appId) {
    this.appId=appId;
    this.hostId="";
    this.sessionId="";
    this.tag={};
    this.load = function () {
        var me = this;
        try{
            var key = ["kmsApp", me.appId].join(".");
            var content = window.localStorage.getItem(key );
            if( content && content!="" ){
                var info = JSON.parse(content);
                me.hostId = info.hostId;
                me.tag = info.tag;
            }
            me.update();
        }
        catch (e) {
            console.log(e);
        }
    };
    this.save = function () {
        var me = this;
        try{
            var key = ["kmsApp", me.appId].join(".");
            var content = JSON.stringify(this);
            window.localStorage.setItem(key , content);
        }
        catch (e) {
            console.log(e);
        }
    };
    this.update = function () {
        var me = this;
        try{
            me.sessionId = getNewId('sid');
            me.hostId = me.hostId&& me.hostId!=null && me.hostId!="" ? me.hostId: getNewId('hid');
            me.save();
        }
        catch (e) {
            console.log(e);
        }
    };
    this.load();
}
function  TKmsMqSessions() {
    this.config={
        host:"gmggf8g.mqtt.iot.bj.baidubce.com",
        port:443,
        uid:"gmggf8g/peer",
        pwd:"a52bwKg22dCAuQzB",
        channelTopic:"hhkms/channel",
        sessionTopic:"hhkms/session",
        channelId:"",
        sessionId:"",
        sessionInfo:{},
        deviceId:""
    };
    this.client = null;
    this.sessions={};
    this.events={
        onSessionChanged:function (ac , sessionId) {

        },
        onRecMsg : function (topic, msg , result) {

        },
        onConnect : function () {

        },
        onDisconnect : function (er) {

        }
    };
    this.open = function (channelId ,sessionId , sessionInfo , deviceId) {
        var res = false;
        var  me = this;
        try {
            me.config.channelId = channelId;
            me.config.sessionId = sessionId;
            me.config.sessionInfo = sessionInfo;
            me.config.deviceId = deviceId;
            me.client = new Paho.Client(me.config.host, Number(me.config.port), me.config.sessionId);
            me.client.onConnected = function(e){
                var channelTopic = [me.config.channelTopic , me.config.channelId , "#"].join("/");
                me.client.subscribe(channelTopic);
                var sessionTopic = [me.config.sessionTopic , me.config.sessionId , "#"].join("/");
                me.client.subscribe(sessionTopic);
                cb(me.events.onConnect);
                var handler = function () {
                    var msgInfo = {
                        ac:"acHello" ,
                        sessionInfo: sessionInfo
                    };
                    me.sendChannelMsg(msgInfo);
                }
                window.setTimeout(handler, 1500);
            };
            me.client.onConnectionLost = function(e){
                cb( me.events.onDisconnect , e);
            };
            me.client.onMessageArrived = function(e){
                var aResult={
                    MsgContent : e.payloadString ,
                    Topic: e.topic,
                    Retain:e.retained,
                    Qos:e.qos
                };
                try {
                    var msgInfo ={};
                    try {
                        msgInfo = JSON.parse(aResult.MsgContent);
                    }
                    catch (eInfo) {
                        console.log(eInfo);
                    }
                    if( msgInfo && msgInfo.ac && msgInfo.ac=="acHello" ){
                        var welcomeMsg = {
                            ac:"acWelcome" ,
                            sessionInfo: sessionInfo
                        };
                        me.sendSessionMsg( msgInfo.srcSessionId, welcomeMsg);
                        if(msgInfo.srcSessionId!= sessionId){
                            me.sessions[msgInfo.srcSessionId] = msgInfo;
                            cb( me.events.onSessionChanged ,  "online" , msgInfo );
                        }
                    }
                    else if( msgInfo && msgInfo.ac && msgInfo.ac=="acWelcome" ){
                        me.sessions[msgInfo.srcSessionId] = msgInfo;
                        cb( me.events.onSessionChanged ,  "online" , msgInfo);

                    }
                    else if( msgInfo && msgInfo.ac && msgInfo.ac=="acBye" ){
                        if( me.sessions[msgInfo.srcSessionId]){
                            delete  me.sessions[msgInfo.srcSessionId];
                            cb( me.events.onSessionChanged ,  "offline" , msgInfo);
                        }
                    }
                    else {
                        cb(me.events.onRecMsg, aResult.Topic, msgInfo, aResult);
                    }
                }
                catch (eer) {
                    console.log(eer)
                }
            };

            var wmsg = new Paho.Message(JSON.stringify({
                ac:"acBye" ,
                deviceId: me.config.deviceId ,
                channelId: me.config.channelId ,
                srcSessionId: me.config.sessionId ,
                sessionInfo: me.config.sessionInfo
            }));
            wmsg.destinationName = me.config.channelTopic+"/"+channelId;
            var connectOptions = {
                invocationContext: {
                    host: me.config.host,
                    port: me.config.port,
                    path: "",
                    clientId: me.config.sessionId
                },
                timeout: 10000,
                keepAliveInterval: 60,
                cleanSession: true,
                useSSL: window.location.href.toLowerCase().indexOf("https://")>=0,
                reconnect: true,
                userName :me.config.uid,
                password :me.config.pwd ,
                willMessage: wmsg ,
                onSuccess: function(e){
                    //GateWay.Callback( GateWay.Events.OnConnected , GateWay);
                },
                onFailure:function(eDis){
                    cb(me.events.onDisconnect , eDis);
                }
            };

            me.client.connect(connectOptions);
            res = me.client.isConnected();
        }
        catch (er) {
            console.log(er)
        }
        return res;
    };
    this.sendChannelMsg = function (msgInfo) {
        var me = this;
        try {
            if( me.client.isConnected()){
                msgInfo.deviceId = me.config.deviceId;
                msgInfo.srcSessionId = me.config.sessionId;
                msgInfo.channelId = me.config.channelId;
                me.client.publish(me.config.channelTopic+"/"+me.config.channelId, JSON.stringify(msgInfo), 0 , false);
            }
        }
        catch (er) {
            console.log(er)
        }
    };
    this.sendSessionMsg = function (sessionId , msgInfo) {
        var me = this;
        try {
            if( me.client.isConnected()){
                msgInfo.deviceId = me.config.deviceId;
                msgInfo.srcSessionId = me.config.sessionId;
                msgInfo.channelId = me.config.channelId;
                var sessionTopic = [me.config.sessionTopic ,  sessionId ].join("/");
                me.client.publish( sessionTopic, JSON.stringify(msgInfo), 0 , false);
            }
        }
        catch (er) {
            console.log(er)
        }
    }
}


function TKmsMq() {
    this.config={
        host:"gmggf8g.mqtt.iot.bj.baidubce.com",
        port:443,
        uid:"gmggf8g/peer",
        pwd:"a52bwKg22dCAuQzB",
        channelTopic:"hhkms/channel",
        sessionTopic:"hhkms/session",
        endId: "" ,
        channelId:"",
        endInfo:{},
        endKmsId:"",
        endHubPortKmsId:""
    };
    this.client = null;
    this.events={
        onSessionChanged:function (ac , sessionInfo) {

        },
        onRecMsg : function (topic, msg , result) {
            
        },
        onConnect : function () {

        },
        onDisconnect : function (er) {

        }
    };
    this.datas={
        msgInfo:{},
        topics:{
            publishChannelTopic:"",
            subscribeChannelTopic:"",
            publishSessionTopic:"",
            subscribeSessionTopic:"",
        },
        sessions:{},
        connectionOptions:{}
    };
    this.getSessionId = function () {
        var me = this;
        try{
            if( (!me.config.infos.sessionId) ||
                me.config.infos.sessionId ==null ||
                me.config.infos.sessionId==""){
                me.config.infos.sessionId = ['kmsid' , ( new Date()).getTime() , parseInt(Math.random()*100000)].join('_');
            }
        }
        catch (e) {
            console.log(e);
        }
        return me.config.infos.sessionId;
    };
    this.getHostId = function () {
        var me = this;
        var res ="";
        try{
            var aKey="hostId";
            var hid = window.localStorage.getItem(aKey);
            if( (!hid) || hid==null || hid.length==0 ){
                hid = ['hostId' , ( new Date()).getTime() , parseInt(Math.random()*100000)].join('_');
            }
            res = hid;
        }
        catch (e) {
            console.log(e);
        }
        return res;
    };
    this.getConnectionOptions = function () {
        var  me = this;
        var res ={};
        try{
            var wmsg = new Paho.Message(JSON.stringify({
                ac:"acOffline" ,
                msg: me.datas.msgInfo
            }));
            wmsg.destinationName = willTopic;
            res = {
                invocationContext: {
                    host: me.config.host,
                    port: me.config.port,
                    path: "",
                    clientId: me.data.msgInfo.sessionId
                },
                timeout: 10000,
                keepAliveInterval: 60,
                cleanSession: true,
                useSSL: window.location.href.toLowerCase().indexOf("https://")>=0,
                reconnect: true,
                userName :me.config.uid,
                password :me.config.pwd ,
                willMessage: wmsg ,
                onSuccess: function(e){
                    //GateWay.Callback( GateWay.Events.OnConnected , GateWay);
                },
                onFailure:function(eDis){
                    cb(me.events.onDisconnect , eDis);
                }
            };
        }
        catch (er) {
            console.log(er);
        }
        return res;
    };
    this.getMsgInfo = function () {
        var me = this;
        var res ={};
        try{
            res = {
                channelId : me.config.channelId ,
                endId: me.config.endId ,
                endInfo : me.config.endInfo ,
                sessionId: me.getSessionId(),
                hostId:me.getHostId() ,
                endKmsId: me.config.endKmsId ,
                endHubPortKmsId: me.config.endHubPortKmsId
            }
        }
        catch (e) {
            console.log(e);
        }
        return res;
    };
    this.initDatas = function () {
        var me = this;
        try{
            me.datas.msgInfo = me.getMsgInfo();
            me.datas.topics.publishChannelTopic = [me.config.channelTopic,me.config.channelId].join("/");
            me.datas.topics.publishSessionTopic = [me.config.sessionTopic,me.config.channelId, me.datas.msgInfo.sessionId].join("/");
            me.datas.topics.subscribeChannelTopic = me.datas.topics.publishChannelTopic+"/#";
            me.datas.topics.subscribeSessionTopic = me.datas.topics.publishSessionTopic+"/#";
            me.datas.connectionOptions = me.getConnectionOptions();
            me.datas.sessions ={};
        }
        catch (e) {
            console.log(e);
        }
    };
    this.open = function ( autoRegist ) {
        var me = this;
        try{
            me.initDatas();
            var cId = me.datas.msgInfo.sessionId;
            var client =  new Paho.Client(host, Number(port), cId);
            client.onConnected = function(e){
                client.subscribe(me.datas.topics.subscribeChannelTopic);
                client.subscribe(me.datas.topics.subscribeChannelTopic);
                cb(me.events.onConnect);
                if( autoRegist){
                    window.setTimeout(me.acRegist, 1500);
                }
            };
            client.onConnectionLost = function(e){
                cb( me.events.onDisconnect , e);
            };
            client.onMessageArrived = function(e){
                var aResult={
                    MsgContent : e.payloadString ,
                    Topic: e.topic,
                    Retain:e.retained,
                    Qos:e.qos
                };
                try {
                    var msgInfo ={};
                    try {
                        msgInfo = JSON.parse(aResult.MsgContent);
                    }
                    catch (eInfo) {
                        console.log(eInfo);
                    }
                    if( msgInfo && msgInfo.ac && msgInfo.ac=="acHello" ){
                        me.doOnHello(msgInfo);
                    }
                    else if( msgInfo && msgInfo.ac && msgInfo.ac=="acHello" ){
                        me.doOnWelcome(msgInfo);
                    }
                    else if( msgInfo && msgInfo.ac && msgInfo.ac=="acHello" ){
                        me.doOnOffline(msgInfo);
                    }
                    else {
                        cb(me.events.onRecMsg, aResult.Topic, msgInfo, aResult);
                    }
                }
                catch (eer) {
                    console.log(eer)
                }
            };
            me.client = client;
            client.connect(me.datas.connectionOptions);
        }
        catch (er) {
            console.log(er);
        }
        return client;
    };
    this.acRegist = function ( autoRegist ) {
        var me = this;
        try{
            var msg = {
                ac:"acHello",
                msg:me.datas.msgInfo
            };
            me.client.publish(me.datas.topics.publishChannelTopic, JSON.stringify(msg), 0, false);
        }
        catch (er) {
            console.log(er);
        }
    };
    this.doOnHello = function ( msgInfo ) {
        var me = this;
        try{
            if(msgInfo.sessionId!=me.datas.msgInfo.sessionId){
                me.datas.sessions[msgInfo.sessionId] = msgInfo;
                cb(me.events.onSessionChanged('acHello', msgInfo));
            }
            var msg = {
                ac:"acWelcome",
                msg:me.datas.msgInfo
            };
            me.client.publish(me.datas.topics.publishChannelTopic, JSON.stringify(msg), 0, false);

        }
        catch (er) {
            console.log(er);
        }
    };
    this.doOnWelcome = function ( msgInfo ) {
        var me = this;
        try{
            me.datas.sessions[msgInfo.sessionId] = msgInfo;
            cb(me.events.onSessionChanged('acWelcome', msgInfo));
        }
        catch (er) {
            console.log(er);
        }
    };
    this.doOnOffline = function ( msgInfo ) {
        var me = this;
        try{
            if(me.datas.sessions[msgInfo.sessionId]){
                delete me.datas.sessions[msgInfo.sessionId];
                cb(me.events.onSessionChanged('acOffline', msgInfo));
            }
        }
        catch (er) {
            console.log(er);
        }
    };
};
function TKmsExData() {
    this.objId="";
    this.appId="";
    this.kmsId="";
    this.parentId ="";
    this.srcId="";
    this.srcUrl="";
    this.kmsType="";
    this.tag ={};
}
function TKmsProxy() {
    this.config={
        kms:{
            kmsTagKey:"kmsTag_v10",
            kurentUrl: "wss://wss.hhdata.cn:8433/kurento",
            kmsPeerOptions: {
                configuration: {
                    "iceServers": [
                        {
                            urls: "stun:223.68.161.139:3478"
                        },
                        {
                            urls: ["turn:223.68.161.139:3478"],
                            username: "kurento",
                            credential: "kurento"
                        }
                    ]
                },
                mediaConstraints: {
                    audio: true,
                    video: {width: {exact: 1280}, height: {exact: 720} , frameRate: 20}
                }
            },
            kmsPeerTypes: {
                send: kurentoUtils.WebRtcPeer.WebRtcPeerSendonly,
                rec: kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly,
                sendRec: kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv
            } ,
            localVideo:null ,
            remoteVideo:null ,
            hubFlag:false
        }
    };
    this.datas={
        kms:{
            kurentoClient: null
        },
        objDicts:{},
        objItems:[]
    };
    this.getKmsClient = function (callback) {
        var me = this;
        try{
            if( me.datas.kms.kurentoClient  && me.datas.kms.kurentoClient!=null){
                cb(callback,me.datas.kms.kurentoClient);
            }
            else{
                kurentoClient(me.config.kms.kurentUrl, function (error, client) {
                    if (client) {
                        me.datas.kms.kurentoClient = client;
                        client.getServerManager(function (erSvr , svr) {
                            client.serverManager = svr;
                            me.updateKmsObjs(function () {
                                cb(callback , client);
                            })
                        })
                    }
                });
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.updateKmsObjs = function (callback) {
        var me = this;
        try{
            me.datas.kms.kurentoClient.serverManager.getTags(function (ertags, tags) {
                var client = me.datas.kms.kurentoClient;
                var svr = client.serverManager;
                if( tags && tags!=null){
                    me.datas.objDicts={};
                    me.datas.objItems=[];
                    var index =0;
                    var loadItem = function(){
                        if( index<tags.length){
                            var tag = tags[index];
                            var info =JSON.parse(tag.value);
                            var kmsId = info.kmsId;
                            client.getMediaobjectById(kmsId, function (erfindObj , kobj) {
                                if( erfindObj){
                                    svr.removeTag(tag.key, function () {
                                        index++;
                                        loadItem();
                                    })
                                }
                                else{
                                    me.datas.objDicts[tag.key] = info;
                                    me.datas.objItems.push(info);
                                    index++;
                                    loadItem();
                                }
                            })
                        }
                        else{
                            cb(callback);
                        }
                    }
                    loadItem();
                }
                else {
                    cb(callback);
                }
            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.setObjInfo = function ( kmsExData , kmsObj ,callback) {
        var me = this;
        try{
            kmsObj.setName( kmsExData.objId , function (erName) {
                me.datas.kms.kurentoClient.serverManager.addTag(kmsExData.objId ,JSON.stringify(kmsExData), function (erTag) {
                    me.datas.objDicts[kmsExData.objId] = kmsExData;
                    me.datas.objItems=[];
                    for( var p in me.datas.objDicts){
                        me.datas.objItems.push(me.datas.objDicts[p]);
                    }
                    cb(callback);
                } )
            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.openChannel = function (channelId , appId , channInfo ,callback) {
        var me = this;
        try{
            me.getKmsClient(function (client) {
                var channel = me.datas.objDicts[channelId];
                if( channel){
                    cb(callback , channel);
                }
                else{
                    client.create("MediaPipeline", function ( erNew , newObj) {
                        var res = new TKmsExData();
                        res.objId = channelId;
                        res.appId = appId;
                        res.tag  = channInfo;
                        res.kmsId = newObj.id;
                        me.setObjInfo(res , newObj , function () {
                            cb(callback, res);
                        })
                    })
                }

            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.openHub = function (channelId , objId, appId , info ,callback) {
        var me = this;
        try{
            var obj = me.datas.objDicts[objId];
            if( obj){
                cb(callback , obj);
                return;
            }
            var chs = $.grep(me.datas.objItems , function (ch , ind) {
                return ch.objId == channelId;
            })
            if( chs.length>0){
                var channelKmsId = chs[0].kmsId;
                me.getKmsClient(function (client) {
                    client.getMediaobjectById(channelKmsId, function (erFind , pipe) {
                        pipe.create("Composite", function (erNew , newObj) {
                            var res = new TKmsExData();
                            res.objId = objId;
                            res.parentId = channelId;
                            res.appId = appId;
                            res.tag  = info;
                            res.kmsId = newObj.id;
                            me.setObjInfo(res , newObj , function () {
                                cb(callback, res);
                            })
                        })
                    })
                })
            }
            else{
                cb(callback);
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.openPlayerEndpoint = function (channelId , objId, appId, srcUrl , info ,callback) {
        var me = this;
        try{
            var obj = me.datas.objDicts[objId];
            if( obj){
                cb(callback , obj);
                return;
            }
            var chs = $.grep(me.datas.objItems , function (ch , ind) {
                return ch.objId == channelId;
            })
            if( chs.length>0){
                var channelKmsId = chs[0].kmsId;
                me.getKmsClient(function (client) {
                    client.getMediaobjectById(channelKmsId, function (erFind , pipe) {
                        pipe.create("PlayerEndpoint",{uri: srcUrl}, function (erNew , newObj) {
                            newObj.on('EndOfStream', function () {
                                newObj.play();
                            })
                            newObj.play();
                            var res = new TKmsExData();
                            res.objId = objId;
                            res.parentId = channelId;
                            res.appId = appId;
                            res.srcUrl = srcUrl;
                            res.tag  = info;
                            res.kmsId = newObj.id;
                            me.setObjInfo(res , newObj , function () {
                                cb(callback, res);
                            })
                        })
                    })
                })
            }
            else{
                cb(callback);
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.openWebRtcEndpoint = function (channelId , objId, appId , info ,callback) {
        var me = this;
        try{
            var obj = me.datas.objDicts[objId];
            if( obj){
                cb(callback , obj);
                return;
            }
            var chs = $.grep(me.datas.objItems , function (ch , ind) {
                return ch.objId == channelId;
            })
            if( chs.length>0){
                var channelKmsId = chs[0].kmsId;
                me.getKmsClient(function (client) {
                    client.getMediaobjectById(channelKmsId, function (erFind , pipe) {
                        pipe.create("WebRtcEndpoint", function (erNew , newObj) {
                            var res = new TKmsExData();
                            res.objId = objId;
                            res.parentId = channelId;
                            res.appId = appId;
                            res.tag  = info;
                            res.kmsId = newObj.id;
                            me.setObjInfo(res , newObj , function () {
                                cb(callback, res);
                            })
                        })
                    })
                })
            }
            else{
                cb(callback);
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.openHubPort = function (hubId , srcId , objId, appId , info ,callback) {
        var me = this;
        try{
            var obj = me.datas.objDicts[objId];
            if( obj){
                cb(callback , obj);
                return;
            }
            var hubs = $.grep(me.datas.objItems , function (ch , ind) {
                return ch.objId == hubId;
            });
            var srcs = $.grep(me.datas.objItems , function (ch , ind) {
                return ch.objId == srcId;
            });
            if( hubs.length>0 && srcs.length>0){
                var hubKmsId = hubs[0].kmsId;
                var srcKmsId = srcs[0].kmsId;
                me.getKmsClient(function (client) {
                    client.getMediaobjectById(hubKmsId, function (erFind , hub) {
                        client.getMediaobjectById(srcKmsId, function (erFind , src) {
                            hub.createHubPort(function (erNew , newObj) {
                                src.connect(newObj, function (erConnect) {
                                    var res = new TKmsExData();
                                    res.objId = objId;
                                    res.parentId = hubId;
                                    res.srcId = srcId;
                                    res.appId = appId;
                                    res.tag  = info;
                                    res.kmsId = newObj.id;
                                    me.setObjInfo(res , newObj , function () {
                                        cb(callback, res);
                                    })
                                })
                            })
                        });
                    })
                })
            }
            else{
                cb(callback);
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.getDevices = function (onGet) {
        var me = this;
        try{
            var res ={};
            navigator.mediaDevices.enumerateDevices().then(function (devs) {
                try {
                    for (var i = 0; i < devs.length; i++) {
                        var item = devs[i];
                        if (!res[item.kind]) {
                            res[item.kind] = []
                        }
                        res[item.kind].push(item);
                    }
                }
                catch (er) {
                    console.log(er)
                }
                cb( onGet , res);
            }).catch(function () {
                cb( onGet , res);
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.setHDWebRtcEndpoint = function ( end, onSet ) {
        var me = this;
        try{
            end.setMaxVideoRecvBandwidth(3000).then(()=>{
                return end.setMaxVideoRecvBandwidth(3000);
            }).then(()=>{
                return end.setMaxVideoSendBandwidth(3000);
            }).then(()=>{
                return end.setMinVideoRecvBandwidth(1500);
            }).then(()=>{
                return end.setMinVideoSendBandwidth(1500);
            }).then(()=>{
                cb( onSet)
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.createPeer = function( localVideo , remoteVideo , onCreatePeer) {
        var me = this;
        try{
            var opts = JSON.parse(JSON.stringify(me.config.kms.kmsPeerOptions));
            opts.localVideo = localVideo;
            opts.remoteVideo = remoteVideo;
            var peer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(opts, function () {
                me.getDevices(function (deviceRes) {
                    peer.devices = deviceRes;
                    cb(onCreatePeer, peer);
                })
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.getNewPeer = function( localVideo , remoteVideo ,  peerType, onCreatePeer) {
        var me = this;
        try{
            var opts = JSON.parse(JSON.stringify(me.config.kms.kmsPeerOptions));
            opts.localVideo = peerType==1?null: localVideo;
            opts.remoteVideo = peerType==0?null: remoteVideo;
            var factories =[
                kurentoUtils.WebRtcPeer.WebRtcPeerSendonly,
                kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly,
                kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv
            ];
            var factory = factories[peerType];
            var peer = factory(opts, function () {
                me.getDevices(function (deviceRes) {
                    peer.devices = deviceRes;
                    cb(onCreatePeer, peer);
                })
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.bindPeerEnd = function (peer , endpoint , callback) {
        var me = this;
        try{
            var setCandidateEvent = function (peer, endpoint) {
                try {
                    if (peer && endpoint) {
                        endpoint.on('OnIceCandidate', function (event) {
                            var candidate = event.candidate;
                            peer.addIceCandidate(candidate);
                            console.log(candidate);
                            console.log('candidate w->p')
                        });
                        peer.on('icecandidate', function (candidate) {
                            var iceCandidate = kurentoClient.register.complexTypes.IceCandidate(candidate);
                            endpoint.addIceCandidate(iceCandidate);
                            console.log(iceCandidate,candidate);
                            console.log('candidate p->w')

                        });
                    }
                } catch (e) {
                    ;
                }
            }
            if (endpoint && peer) {
                peer.generateOffer(function (errorPeerGenerateOffer, sdpOffer) {
                    if (errorPeerGenerateOffer && callback) {
                        callback(errorPeerGenerateOffer, null);
                    } else {
                        endpoint.processOffer(sdpOffer, function (errorSdpOffer, sdpAnswer) {
                            if (errorSdpOffer && callback) {
                                console.log("process sdpOffer error.", errorSdpOffer)
                                callback(errorSdpOffer, null);
                            } else {
                                setCandidateEvent(peer, endpoint);
                                peer.processAnswer(sdpAnswer);
                                endpoint.gatherCandidates(function (errorGatherCandidates) {
                                    if (errorGatherCandidates && callback) {
                                        console.log('webRtcPoint gatherCandidates error.', errorGatherCandidates)
                                        callback(errorGatherCandidates, null);
                                    } else {
                                        peer.endpoint = endpoint;
                                        endpoint.peer = peer;
                                        setCandidateEvent(peer, endpoint);
                                        if (callback) {
                                            callback(null, {endpoint: endpoint, peer: peer});
                                        }
                                    }
                                });
                            }
                        });
                    }
                });
            } else {
                if (callback) {
                    callback({error: "endPoint or peer is null."}, null);
                }
            }

        }
        catch (e) {
            console.log(e);
        }
    };
    this.acSetCamera = function ( peer ,  cameraDeviceId ,onSetCamera) {
        var me = this;
        try{
            if (window.rtcVideoStream) {
                window.rtcVideoStream.getTracks().forEach(track => {
                    if( track.kind=="video") {
                        track.stop();
                    }
                });
            }
            var constraints = {video: {deviceId: cameraDeviceId , height:{exact:720} , width:{exact:1280}}};
            var sender= null;
            navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
                try {
                    window.rtcVideoStream = stream;
                    peer.localVideo.srcObject = stream;
                    let videoTrack = stream.getVideoTracks()[0];
                    sender = peer.peerConnection.getSenders().find(function (s) {
                        return s.track.kind == videoTrack.kind;
                    });
                    sender.replaceTrack(videoTrack);
                    cb(onSetCamera);
                }
                catch (eSet) {
                    cb( onSetCamera);
                }
            }).catch(function () {
                cb(onSetCamera);
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acSwitchCamera = function (peer) {
        var me = this;
        try{
            var ids =[
                peer.devices.videoinput[0].deviceId ,
                peer.devices.videoinput[peer.devices.videoinput.length-1].deviceId
            ];
            var cameraId = (
                peer.cameraId  &&
                peer.cameraId !=null &&
                peer.cameraId.length>0 )?peer.cameraId : "";
            cameraId = cameraId == ids[1]?ids[0]:ids[1];
            me.acSetCamera(peer , cameraId , function () {
                peer.cameraId = cameraId;
            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acToggleAudioMute = function (peer) {
        var me = this;
        try{
            peer.peerConnection.audioEnabled = !peer.peerConnection.audioEnabled;
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acToggleVideoMute = function (peer) {
        var me = this;
        try{
            peer.peerConnection.videoEnabled = !peer.peerConnection.videoEnabled;
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acTogglePlayVolume = function (peer) {
        var me = this;
        try{
            peer.remoteVideo.volume = peer.remoteVideo.volume==0?1:0;
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acShareScreen = function (peer ,width , height) {
        var me = this;
        try{
            var wWidth = width?width : $(window).width();
            var wHeight = height?height: $(window).height();
            var screenConstraints = {video: {width: {max:wWidth}, height: {max: wHeight}}, audio: true};
            var sender= null;
            if (navigator.mediaDevices.getDisplayMedia) {
                navigator.mediaDevices.getDisplayMedia(screenConstraints).then(
                    function (stream) {
                        let videoTrack = stream.getVideoTracks()[0];
                        peer.localVideo.srcObject = stream;
                        sender = peer.peerConnection.getSenders().find(function (s) {
                            return s.track.kind == videoTrack.kind;
                        });
                        sender.track.stop();
                        sender.replaceTrack(videoTrack);
                    }
                )
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acFullScreen = function (peer) {
        var element = peer.remoteVideo;
        if (element.requestFullscreen) {
            element.requestFullscreen();
        } else if (element.msRequestFullscreen) {
            element.msRequestFullscreen();
        } else if (element.mozRequestFullScreen) {
            element.mozRequestFullScreen();
        } else if (element.webkitRequestFullscreen) {
            element.webkitRequestFullscreen();
        }
    };
}
function  TKmsApi() {
    this.config={
        appId: "hhRa",
        apiUrl: "https://wss.hhdata.cn:20024/api/"
    };
    this.appInfo = new TKmsApp(this.config.appId);
    this.callApi = function (ac, ps, callback) {
        var me = this;
        try {
            var url = me.config.apiUrl + ac + "?tmrnd=" + (new Date()).getTime().toString();
            /*
            $.post( url , ps , function (res) {
                    try{
                        var result = JSON.parse(res);
                        hhls.callBack(callback , result);
                    }
                    catch (er0) {
                        console.log(er0);
                    }
                } );
             */
            $.ajax({
                url: url,
                data: ps,
                //type:"POST",
                //contentType:"JSON",
                success: function (res) {
                    try {
                        var result = JSON.parse(res);
                        cb(callback, result);
                    } catch (er0) {
                        console.log(er0);
                    }
                },
                error: function (errRes) {
                    try {
                        cb(callback, errRes);
                    } catch (er0) {

                    }
                }
            })
        } catch (e) {
            console.log(e)
        }
    };
    this.dbQuery = function (key, ps, callback) {
        var me = this;
        try {
            var ac = "acQuery";
            var psJson = JSON.stringify(ps);
            var psData = {
                appId: me.config.appId,
                key: key,
                ps: psJson
            };
            me.callApi(ac, psData, callback);
        } catch (e) {
            console.log(e)
        }
    };
    this.checkTel  = function (telCode) {
        return /^[1][3,4,5,7,8,9][0-9]{9}$/.test(telCode);
    };
    this.validCheckCode  = function (tel , clientTm , code , secCode) {
        var flag = false;
        var clientCode = [tel , clientTm.toString(), "60000" , code].join("-");
        clientCode = $.md5(clientCode);
        flag = clientCode == secCode;
        return flag;
    };
    this.requestCode = function (tel, callback) {
        var me = this;
        try {
            var ac = "acSendSmsCheckCode";
            var psData = {
                ct: ( new Date()).getTime(),
                tel: tel
            };
            me.callApi(ac, psData, callback);
        } catch (e) {
            console.log(e)
        }
    };
};

hhClient = {
    api: new TKmsApi(),
    //kmsClient : new TKmsClientV10() ,
    kmsProxy: new TKmsProxy(),
    mq : new TKmsMq()
};
